#include "stdafx.h"


static SDL_Surface *mScreen;

SDLAdapter::SDLAdapter(){

}

SDL_Surface* SDLAdapter::getScreen(){
	return mScreen;
}

void SDLAdapter::drawImage(SDL_Surface *image, int xPos, int yPos, int w, int h){
	SDL_Rect destination;
	destination.x = xPos;
	destination.y = yPos;
	destination.h = h;
	destination.w = w;
	/* Blit onto the screen surface */
	if(SDL_BlitSurface(image, NULL, mScreen, &destination) < 0)
		fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError());
}

SDL_Surface *SDLAdapter::loadBitmap(char *file_name, int xPos, int yPos, int w, int h){
	SDL_Surface *image;

	/* Load the BMP file into a surface */
    image = SDL_LoadBMP(file_name);
    if (image == NULL) {
        fprintf(stderr, "Couldn't load %s: %s\n", file_name, SDL_GetError());
        return NULL;
    }

	 /*
     * Palettized screen modes will have a default palette (a standard
     * 8*8*4 colour cube), but if the image is palettized as well we can
     * use that palette for a nicer colour matching
     */
    if (image->format->palette && mScreen->format->palette) {
    SDL_SetColors(mScreen, image->format->palette->colors, 0,
                  image->format->palette->ncolors);
    }

	return image;
}

int SDLAdapter::isKeyDown (int pKey)
{
	Uint8* mKeytable;
	int mNumkeys;
	SDL_PumpEvents();
	mKeytable = SDL_GetKeyState(&mNumkeys);
	return mKeytable[pKey];
}

int SDLAdapter::pollkey()
{
	SDL_Event event;
	while ( SDL_PollEvent(&event) ) 
	{
		switch (event.type) {
			case SDL_KEYDOWN:
				return event.key.keysym.sym;
			case SDL_QUIT:
				exit(3);
		}
	}
	return -1;
}

/* 
======================================									
Keyboard Input
====================================== 
*/
int SDLAdapter::getkey()
{
	SDL_Event event;
	while (true)
	{
	  SDL_WaitEvent(&event);
	  if (event.type == SDL_KEYDOWN)
		  break;
      if (event.type == SDL_QUIT)
		  exit(3);
	};
	return event.key.keysym.sym;
}


void SDLAdapter::startGame(SDL_Surface *title){
	//Pieces
	Pieces mPieces;

	// Board
	Board mBoard (&mPieces, mScreen->h);

	// Game
	Game mGame (&mBoard, &mPieces, this, mScreen->h);

	// Get the actual clock milliseconds (SDL)
	unsigned long mTime1 = SDL_GetTicks();

	// ----- Main Loop -----

	while (!isKeyDown (SDLK_ESCAPE))
	{
		// ----- Draw -----

		clearScreen (); 		// Clear screen 
		drawImage(title,50,50,441,52);
		mGame.DrawScene ();			// Draw staff
		refreshScreen ();		// Put the graphic context in the screen

		// ----- Input -----

		int mKey = pollkey();

		switch (mKey)
		{
			case (SDLK_RIGHT): 
			{
				if (mBoard.IsPossibleMovement (mGame.mPosX + 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
					mGame.mPosX++;
					break;
			}

			case (SDLK_LEFT): 
			{
				if (mBoard.IsPossibleMovement (mGame.mPosX - 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
					mGame.mPosX--;	
				break;
			}

			case (SDLK_DOWN):
			{
				if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY + 1, mGame.mPiece, mGame.mRotation))
					mGame.mPosY++;	
				break;
			}

			case (SDLK_x):
			{
				// Check collision from up to down
				while (mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation)) { mGame.mPosY++; }
	
				mBoard.StorePiece (mGame.mPosX, mGame.mPosY - 1, mGame.mPiece, mGame.mRotation);

				mBoard.DeletePossibleLines ();

				if (mBoard.IsGameOver())
				{
					getkey();
					exit(0);
				}

				mGame.CreateNewPiece();

				break;
			}

			case (SDLK_z):
			{
				if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY, mGame.mPiece, (mGame.mRotation + 1) % 4))
					mGame.mRotation = (mGame.mRotation + 1) % 4;

				break;
			}
		}

		// ----- Vertical movement -----

		unsigned long mTime2 = SDL_GetTicks();

		if ((mTime2 - mTime1) > WAIT_TIME)
		{
			if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY + 1, mGame.mPiece, mGame.mRotation))
			{
				mGame.mPosY++;
			}
			else
			{
				mBoard.StorePiece (mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation);

				mBoard.DeletePossibleLines ();

				if (mBoard.IsGameOver())
				{
					getkey();
					exit(0);
				}

				mGame.CreateNewPiece();
			}

			mTime1 = SDL_GetTicks();
		}
	}


}

void SDLAdapter::DrawRectangle(int pX1, int pY1, int pX2, int pY2, enum color pC) {
	boxColor (mScreen, pX1, pY1, pX2, pY2-1, mColors[pC]);
}

void SDLAdapter::drawSquare(int xPos, int yPos){
	clearScreen();
	boxColor (mScreen, xPos, yPos, xPos+20, yPos+20, 0xff0000ff);
	refreshScreen();
}

void SDLAdapter::clearScreen(){
	boxColor (mScreen, 0, 0, mScreen->w - 1, mScreen->h - 1, 0x000000ff);
}


void SDLAdapter::refreshScreen(){
	SDL_Flip(mScreen);
}

void SDLAdapter::initSDLGraphics(){
	
	const SDL_VideoInfo *info;
	Uint8  video_bpp;
	Uint32 videoflags;

	printf("Initializing SDL.\n");
    
    /* Initialize defaults, Video and Audio */
    if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) { 
        printf("Could not initialize SDL: %s.\n", SDL_GetError());
        exit(-1);
	}

	atexit(SDL_Quit);

	info = SDL_GetVideoInfo();
	if ( info->vfmt->BitsPerPixel > 8 ) {
		video_bpp = info->vfmt->BitsPerPixel;
	} else {
		video_bpp = 16;
	}
	videoflags = SDL_SWSURFACE | SDL_DOUBLEBUF;

	mScreen=SDL_SetVideoMode(640,480,video_bpp,videoflags);

    if ( mScreen == NULL ) {
        fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
                        SDL_GetError());
        exit(1);
	}

    printf("SDL initialized.\n");
}

void SDLAdapter::shutdownGraphics(){
	printf("Quiting SDL.\n");

        /* Clean up on exit */
    atexit(SDL_Quit);


    printf("Quiting....\n");

    exit(0);
}

